/*
 * @Author: _LJP 2634716776@qq.com
 * @Date: 2023-12-22 10:00:08
 * @LastEditors: _LJP 2634716776@qq.com
 * @LastEditTime: 2023-12-23 22:24:46
 * @FilePath: /my_-linux/Pro23/Map/MapTest/test.cpp
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE```
 */
#include<iostream>

using namespace std;

#include<map>

#include<string>

/*
    序列式容器(key,value模型),顾名思义保存一个key值以及value值
    其中key值作为键值不可被修改,但value值可被修改
    其中key,value模型的实现底层即为 typedef pair<const Key,T> value_type的数据结构
    其中pair的结构大致为

     template<typename _T1, typename _T2>
    struct pair
    : private __pair_base<_T1, _T2>
    {
      typedef _T1 first_type;
      typedef _T2 second_type;

      _T1 first;
      _T2 second;
    
        explicit constexpr pair()
        : first(), second() { }
    }

    一般情况下可以用make_pair()函数创建pair
*/

void map_test1(){
    /*
        字典
    */
   map<string,string> dict;
   
   dict.insert({"string","字符串"});    //通过传参让pair自行构造  
   dict.insert(make_pair("sort", "排序"));  //使用make_pair()函数构造
   dict.insert(pair<string, string>("list", "链表")); // 原生调用匿名对象

   dict.insert(make_pair("list", "(链表)"));//  erro - 插入失败 key值不能被修改 

   for(auto it: dict){
        cout<<it.first<<" : "<<it.second<<endl;
   }

   map<string,string>::iterator it = dict.begin();
   while(it!=dict.end()){
       cout << (*it).first << " : " <<(*it).second << " ";
       cout << it->first << " : " << it->second << " | ";//调用了operator->()
       ++it;
   }
   cout<<endl;
}

void map_test2(){
/*
    统计水果出现的次数
*/
    map<string,int> fruit;

    string f[] = { "香蕉", "菠萝", "橘子", "苹果", "菠萝", "柚子", "菠萝", "香蕉", "菠萝" };

    // for( auto &it : f ){
    //     if(fruit.count(it) == 0){
    //         fruit.insert({ it , 1 });
    //     }
    //     else fruit.find( it )->second++;
    // }

    for( auto &it : f ){
        //直接调用operator[]对value值进行增加
        fruit[it]++;
    }


    for( auto &it : fruit ){
        cout << it.first << " : " << it.second << endl ;
    }
}

void map_test3()
{
    /*
        map中的operator[]本质上可以理解为如下:

        V& operator[](const K& key){
            pair<iterator,bool> ret = insert(make_pair(key,V()));
            return ret.first->second;
        }
        operator[]的实现主要为一个insert函数
        insert函数返回的是一个pair数据结构,其中键值key于数据value分别为 迭代器iterator 与 布尔值bool类型
        返回时返回该结果pair的first即为该节点的迭代器
        通过该迭代器使用operator->返回节点的second即为节点的value值
        其中返回值V&为 value 的引用

        所以本质上map中的[]可以具有几个功能: 插入 , 查找 , 修改 , 插入+修改
        将在下面示例中进行验证:
    */

    map<string, int> fruit;

    string f[] = {"香蕉", "菠萝", "橘子", "苹果", "菠萝", "柚子", "菠萝", "香蕉", "菠萝"};

    for (auto &it : f)
    {
        // 仅使用[]不对其进行其他操作,该操作为插入(创建key键值)
        fruit[it];
    }
    fruit.clear();//清理map

    for (auto &it : f)
    {
        // 使用[]对map进行插入并对其value进行修改(修改不进行演示)
        fruit[it]++;
    }

    for(auto &it : f){
        // key键值不存在时为插入键值,key键值存在时将会返回其value值起到查询作用
        cout<<fruit[it]<<" ";
    }
    cout<<endl;

}

void multimap_test1(){
    /*
        multimap 与 multiset 的点相同,都为允许键值冗余
    */
    multimap<string, string> dict;

    dict.insert({"string", "字符串"});                 // 通过传参让pair自行构造
    dict.insert(make_pair("sort", "排序"));            // 使用make_pair()函数构造
    dict.insert(pair<string, string>("list", "链表")); // 原生调用匿名对象

    dict.insert(make_pair("list", "(链表)")); 
    /*
        验证multimap允许键值冗余
        该处再次插入了一个list的键值
        插入成功
    */
    multimap<string,string>::iterator it = dict.begin();
    
    while(it != dict.end()){
        cout << it->first << " : " << it->second << endl ;
        ++it;
    }

}

int main()
{
    /*cout<<"hello world"<<endl;*/

    // map_test1();

    // map_test2();

    // map_test3();

    multimap_test1();

    return 0;
}